#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//存储员工信息的结构体
typedef struct employee        	
{
    int num;                   	//员工号
    char duty[10];             	//员工职务
    char name[10];             	//员工姓名
    char sex[3];               	//员工性别
    unsigned char age;         	//员工年龄
    char edu[10];              	//教育水平
    int salary;                	//员工工资
    char tel_office[13];       	//办公电话
    char tel_home[13];         	//家庭电话
    char mobile[13];           	//手机
    char qq[11];               	//qq号码
    char address[31];          	//家庭住址
    struct employee *next;
}EMP;
//全局变量
char password[9];          		//系统密码
EMP *emp_first,*emp_end;   		//定义指向链表的头结点和尾节点的指针
char gsave,gfirst;         		//判断标示

//自定义函数声明
void addemp(void);         	 	//添加员工信息的函数
void findemp(void);        	 	//查找员工信息的函数
void listemp(void);        		//显示员工信息列表的函数
void modifyemp(void);      	 	//修改员工信息的函数
void summaryemp(void);     	 	//统计员工信息的函数
void delemp(void);         	 	//删除员工信息的函数
void resetpwd(void);       		//重置系统的函数
void readdata(void);       		//读取文件数据的函数
void savedata(void);       		//保存数据的函数
int modi_age(int s);       		//修改员工年龄的函数
int modi_salary(int s);    	 	//修改员工工资的函数
char *modi_field(char *field,char *s,int n);      		//修改员工其他信息的函数
EMP *findname(char *name);                        		//按员工姓名查找员工信息
EMP *findnum(int num);                            	 	//按员工工号查找员工信息
EMP *findtelephone(char *name);                   		//按员工的通讯号码查找员工信息
EMP *findqq(char *name);                          	 	//按员工的QQ号查找员工信息
void displayemp(EMP *emp,char *field,char *name); 		//显示员工信息
void checkfirst(void);                            		//初始化检测
void bound(char ch,int n);                        		//画出分界线
void login();                                     		//登录检测
void menu();                                      		//主菜单列表

/*
员工信息添加
*/
void add_emp()
{
    FILE *fp;
    EMP *emp1;
    int i=0;
    char choice='y';

    if ((fp = fopen("employee.dat", "ab")) == NULL)
    {
        printf("打开文件employee.dat出错！\n");
        getchar();
        return;
    }
    do
    {
        i++;
        emp1 = (EMP *)malloc(sizeof(EMP));
        if (emp1 == NULL)
        {
            printf("内存分配失败，按任意键退出！\n");
            getchar();
            return;
        }
        printf("请输入第%d个员工的信息，\n",i);
        bound('_',30);
        printf("工号：");
        scanf("%d",&emp1->num);

        printf("职务：");
        scanf("%s",&emp1->duty);

        printf("姓名：");
        scanf("%s",&emp1->name);

        printf("性别：");
        scanf("%s",&emp1->sex);

        printf("年龄：");
        scanf("%d",&emp1->age);

        printf("文化程度：");
        scanf("%s",&emp1->edu);

        printf("工资：");
        scanf("%d",&emp1->salary);

        printf("办公电话：");
        scanf("%s",&emp1->tel_office);

        printf("家庭电话：");
        scanf("%s",&emp1->tel_home);

        printf("移动电话：");
        scanf("%s",&emp1->mobile);

        printf("QQ:");
        scanf("%s",&emp1->qq);

        printf("地址：");
        scanf("%s",&emp1->address);

        emp1->next = NULL;
        if (emp_first == NULL)
        {
            // 如果这是第一个结点，头尾指针都指向它
            emp_first = emp1;
            emp_end = emp1;
        }
        else
        {
            // 否则尾节点后移
            emp_end->next = emp1;
            emp_end = emp1;
        }
        // 对数据流添加数据项
        fwrite(emp_end, sizeof(EMP), 1, fp);

        gfirst = 0;
        printf("\n");
        bound('-', 30);
        printf("\n是否继续输入？(y/n)");
        fflush(stdin);          // 清空标准输入(stdin)的缓冲区
        choice = getchar();

        if (toupper(choice) != 'Y')
        {
            fclose(fp);
            printf("\n输入完毕，按任意键返回\n");
            getchar();
            return;
        }
        system("cls");
    } while (1);
    
}
// 工具函数，用于输出多个相同字符
void bound(char ch, int n)
{
    while(n--)
    {
        putchar(ch);
    }
    putchar("\n");
    return;
}
/*
首次使用，需要进行用户信息初始化
*/
void check_first()
{
    FILE *fp, *fp1;
    char pwd[9], pwd1[9], pwd2[9], pwd3[9];
    int i;
    char strt = '8';

    if ((fp=fopen("config.bat", "rb")) == NULL)
    {
        printf("\n新系统，请进行相应的初始化工作！\n");
        bound('-', 50);
        getchar();

        do
        {
            printf("\n设置密码，请不要超过8位：");
            for (i=0; i<8 && (pwd[i]=getchar() != 13); i++)
                putch('*');
            printf("\n再确认一次密码：");
            for (i=0; i<8 && (pwd[i]=getchar() != 13); i++)
                putch('*');
            pwd[i] = '\0';
            pwd1[i] = '\0';

            if (strcmp(pwd, pwd1) != 0)
                printf("\n两次密码不一致，请重新输入！\n");
            else
                break;
        } while (1);
        
        if ((fp1 = open("config.bat", "wb")) == NULL)
        {
            printf("\n系统创建失败，按任意键退出！");
            getchar();
            exit(1);
        }
        i=0;
        while (pwd[1])
        {
            // 使用XOR运算对密码进行加密
            pwd2[i] = (pwd[i] ^ strt);
            putw(pwd2[i], fp1);
            i++;
        }
        fclose(fp1);
        printf("\n系统初始化成功 ，按任意键退出后，再重新进入。\n");
        getchar();
        exit(1);
    }
    else
    {
        i = 0;
        // 判断是否读完密码文件
        while (!feof(fp) && i<8)
        {
            // 读出密码解码后赋给数组
            pwd[i++] = (getw(fp) ^ strt);
        }
        pwd[i] = '\0';

        if (i>=8)
            i--;
        while (pwd[i] != -1 && i >=0)
        {
            i--;
        }
        // 最后一位字符串结束字符'\0'
        pwd[i] = '\0';
        strcpy(password, pwd);
    }
}
void delemp()
{
    int find_ok = 0;
    EMP *emp1, *emp2;
    char name[10], choice;
    system("cls");
    printf("\n输入想要删除的员工姓名：");
    scanf("%d", name);
    // emp2是工作指针的前驱结点
    emp1 = emp_first;
    emp2 = emp1;

    while (emp1)
    {
        if (strcmp(emp1->name, name) == 0)
        {
            find_ok = 1;
            system("cls");
            printf("员工：%s的信息如下：\n",emp1->name);
            bound('_',40);
            printf("工号：%d\n",emp1->num);
            printf("职务：%s\n",emp1->duty);
            printf("姓名：%s\n",emp1->name);
            printf("性别：%s\n",emp1->sex);
            printf("年龄：%d\n",emp1->age);
            printf("文化程度：%s\n",emp1->edu);
            printf("工资：%d\n",emp1->salary);
            printf("办公电话：%s\n",emp1->tel_office);
            printf("家庭电话：%s\n",emp1->tel_home);
            printf("移动电话：%s\n",emp1->mobile);
            printf("QQ号码：%s\n",emp1->qq);
            printf("住址:%\n",emp1->address);
            bound('_',40);
            printf("您真的要删除该员工吗？(y/n)");
            // 清除缓冲区
            fflush(stdin);
            choice = getchar();
            
            if (choice != 'y' && choice != 'Y')
                return;
            // 删除结点是首地址
            if (emp1 == emp_first)
                emp_first = emp1->next;
            else
                emp2->next = emp1->next;
            printf("员工%s已被删除。", emp1->name);
            getchar();
            free(emp1);
            gsave = 1;
            savedata();
            return;
        }
        // 查找下一个
        else
        {
            emp2 = emp1;
            emp1 = emp1->next;
        }
    }
    // 没有找到信息
    if (!find_ok)
    {
        bound('-', 40);
        printf("\n没有找到姓名是：%s的员工！\n", name);
        getchar();
    }
    return;
}
void displayemp(EMP *emp, char *field, char *name)
{
    if (emp)
    {
        printf("\n%s:%s信息如下：\n",  field, name);
                bound('_',30); 
        printf("工号：%d\n",emp->num);
        printf("职务：%s\n",emp->duty);
        printf("姓名：%s\n",emp->name);
        printf("性别：%s\n",emp->sex);
        printf("年龄：%d\n",emp->age);
        printf("文化程度：%s\n",emp->edu);
        printf("工资：%d\n",emp->salary);
        printf("办公电话：%s\n",emp->tel_office);
        printf("家庭电话：%s\n",emp->tel_home);
        printf("移动电话：%s\n",emp->mobile);
        printf("QQ号码：%s\n",emp->qq);
        printf("住址:%s\n",emp->address);
        bound('_',30);
    }
    else
    {
        bound('_', 40);
        printf("资料库里面没有%s为：%s的员工！请重新确认！", field, name);
    }
}
/*
按照姓名查找员工信息
*/
EMP *findname(char *name)
{
    EMP *emp1;
    emp1 = emp_first;
    while (emp1)
    {
        // 找到了
        if (strcmp(name, emp1->name) == 0)
            return emp1;
        // 没找到继续往后面遍历查找
        emp1 = emp1->next;
    }
    return NULL;
}
/*
按照员工号查找员工信息
*/
EMP *findnum(int num)
{
    EMP *emp1;
    emp1 = emp_first;
    while (emp1)
    {
        // 找到了
        if (emp1 == emp1->num)
            return emp1;
        // 没找到继续往后面遍历查找
        emp1 = emp1->next;
    }
    return NULL;
}
/*
按照电话号码查找员工信息
*/
EMP *findtelephone(char *name)
{
    EMP *emp1;
    emp1 = emp_first;
    while(emp1)
    {
        if((strcmp(name, emp1->tel_office) == 0)||
        (strcmp(name, emp1->tel_home) == 0)||
        (strcmp(name, emp1->mobile) == 0))
            return emp1;
        emp1 = emp1->next;
    }
    return NULL;
}
/*
按照QQ号来查找员工信息
*/
EMP *findqq(char *name)
{
    EMP *emp1;
    emp1 = emp_first;
    while (emp1)
    {
        if (strcmp(name, emp1->qq) == 0)
            return emp1;
        emp1 = emp1->next;
    }
    return NULL;
}
/*
查询员工信息
*/
void findemp()
{
    int choice, ret = 0, num;
    char str[13];
    EMP  *emp1;
    system("cls");

    do
    {
        printf("\t查询员工信息\n");
        bound('_',30);
        printf("\t1.按姓名查询\n");
        printf("\t2.按工号查询\n");
        printf("\t3.按电话查询\n");
        printf("\t4.按QQ号查询\n");
        printf("\t0.返回主菜单\n");
        bound('_',30);
        printf("\n请选择菜单：");

        do
        {
            fflush(stdin);
            choice = getchar();
            system("cls");

            switch (choice)
            {
            case 1:
                printf("\n输入想要查询的员工姓名：");
                scanf("%s", str);

                emp1 = findname(str);
                displayemp(emp1, "姓名",str);
                getchar();
                break;
            
            case 2:
                printf("\n输入想要查询的员工工号：");
                scanf("%d", &num);

                emp1 = findnum(num);
                // 将整数num转换为十进制字符串，并将结果存储在str字符数组中
                itoa(num, str, 10);
                displayemp(emp1, "工号",str);
                getchar();
                break;
            
            case 3:
                printf("\n输入想要查询的员工电话：");
                scanf("%s", str);

                emp1 = findtelephone(str);
                displayemp(emp1, "电话",str);
                getchar();
                break;
            
            case 4:
                printf("\n输入想要查询的员工QQ号：");
                scanf("%s", str);

                emp1 = findqq(str);
                displayemp(emp1, "QQ号码",str);
                getchar();
                break;
            
            case '0':
                ret = 1;
                break;
            
            default:
                break;
            }
        } while (choice < '0' || choice > '4');
        system("cls");
        if (ret)
            break;
    } while (1);   
}
void listemp()
{
    EMP *emp1;
    printf("\n资料库中的员工信息列表\n");
    bound('_', 40);
    emp1 = emp_first;
    while (emp1)
    {
        printf("工号：%d\n",emp1->num);
        printf("职务：%s\n",emp1->duty);
        printf("姓名：%s\n",emp1->name);
        printf("性别：%s\n",emp1->sex);
        printf("年龄：%d\n",emp1->age);
        printf("文化程度：%s\n",emp1->edu);
        printf("工资：%d\n",emp1->salary);
        printf("办公电话：%s\n",emp1->tel_office);
        printf("家庭电话：%s\n",emp1->tel_home);
        printf("移动电话：%s\n",emp1->mobile);
        printf("QQ号码：%s\n",emp1->qq);
        printf("住址:%s\n",emp1->address);  
        bound('_',40);
        emp1 = emp1->next;
    }
    printf("\n显示完毕，按任意键退出。\n");
    getchar();
}
/*
检测登录密码
*/
void login()
{
    // n 代表允许密码输错的次数
    int i, n=3;
    char pwd[9];
    do
    {
        printf("请输入密码：");
        for (i=0; i<8 && (pwd[i] = getchar()) != 13; i++)
            putch('*');
        pwd[i] = '\0';
        if (!strcmp(pwd, password))
        {
            printf("\n密码错误，请重新输入！\n");
            getchar();
            system("cls");
            n--;
        }
        else
            break;
    } while (n>0);
    if (n == 0)
    {
        printf("您已输入三次错误密码，请退出！\n");
        getchar();
        exit(1);
    }
}
void menu()
{
    char choice;
    system("cls");
    do
    {
    	printf("\n\t\t\t\t 企业员工管理系统\n\n");
        printf("\t\t\t-------------------------------------\n");
        printf("\t\t\t|\t\t\t\t    |\n");
        printf("\t\t\t|  \t1、输入员工信息\t\t    |\n");
        printf("\t\t\t|\t\t\t\t    |\n");
        printf("\t\t\t|  \t2、查询员工信息\t\t    |\n");
        printf("\t\t\t|\t\t\t\t    |\n");
        printf("\t\t\t|  \t3、显示员工信息\t\t    |\n");
        printf("\t\t\t|\t\t\t\t    |\n");
        printf("\t\t\t|  \t4、修改员工信息\t\t    |\n");
        printf("\t\t\t|\t\t\t\t    |\n");
        printf("\t\t\t|  \t5、删除员工信息\t\t    |\n");
        printf("\t\t\t|\t\t\t\t    |\n");
        printf("\t\t\t|  \t6、统计员工信息\t\t    |\n");
        printf("\t\t\t|\t\t\t\t    |\n");
        printf("\t\t\t|  \t7、重置系统密码\t\t    |\n");
        printf("\t\t\t|\t\t\t\t    |\n");
        printf("\t\t\t|  \t0、退出系统\t\t    |\n");
        printf("\t\t\t|\t\t\t\t    |\n");
        printf("\t\t\t-------------------------------------\n");
        printf("\n\t\t\t请选择您需要的操作：");
        do
        {
            fflush(stdin);
            choice = getchar();
            if (gfirst)
            {
                printf("系统中无员工信息，请先添加员工信息！\n");\
                getchar();
                break;
            }
            system("cls");
            switch (choice)
            {
            case '1': add_emp();break;          // 员工信息添加函数
            case '2': findemp();break;          // 员工信息查找函数
            case '3': listemp();break;          // 员工信息列表函数
            case '4': modifyemp();break;        // 员工信息修改函数
            case '5': delemp();break;           // 员工信息删除函数
            case '6': summaryemp();break;       // 员工信息统计函数
            case '7': resetpwd();break;         // 重置系统
            case '0': savedata();exit(0);       // 员工信息保存函数
            default:
                printf("请输入0~7之间的数字\n");
                getchar();
                break;
            }
        } while (choice<'0' || choice>'7');
        system("cls");
    } while (1);    
}

int modi_salary(int salary)
{
    int new_salary;
    printf("原来的工资数：%d", salary);
    printf("新的工资数：");
    scanf("%d", &new_salary);
    return (new_salary);
}
int modi_age(int age)
{
    int new_age;
    printf("原来的工资数：%d", age);
    printf("新的工资数：");
    scanf("%d", &new_age);
    return (new_age);
}
char *modi_field(char *field, char *content, int len)
{
    char *str;
    str = malloc(sizeof(char) * len);
    if (str == NULL)
    {
        printf("内存分配失败，按任意键退出！");
        getchar();
        return NULL;
    }
    printf("原来%s为：%s\n", field, content);
    printf("修改为（内容不要超过%d个字符！）：", len);
    scanf("%s", str);
    return str;
}
void modify_emp()
{
    EMP *emp1;
    char name[10], *new_content;
    int choice;
    
    printf("\n请输入你要修改的员工的姓名：");
    scanf("%s", &name);

    emp1 = findname(name);
    displayemp(emp1, "姓名", name);
    if (emp1)
    {
        printf("\n 请输入你要修改的内容选项！\n");
        bound('_',40);
        printf("1.修改职务                2.修改年龄\n");
        printf("3.修改文化程度            4.修改工资\n");
        printf("5.修改办公室电话          6.修改家庭电话\n");
        printf("7.修改移动电话            8.修改QQ号码 \n");
        printf("9.修改住址                0.返回\n  ");
        bound('_',40);
        
        do
        {
            fflush(stdin);
            choice = getchar();
            switch (choice)
            {
            case '1':
                // 修改基本信息
                new_content = modi_field("职务", emp1->duty, 10);
                if (new_content != NULL)
                {
                    strcmp(emp1->duty, new_content);
                    free(new_content);
                }
                break;
            case '2':
                emp1->age = modi_age(emp1->age);
                break;
            case '3':
                new_content = modi_field("文化程度", emp1->edu, 10);
                if (new_content != NULL)
                {
                    strcpy(emp1->edu, new_content);
                    free(new_content);
                }
                break;
            case '4':
                emp1->salary = modi_salary(emp1->salary);
                break;
            case '5':
                new_content = modi_field("办公室电话", emp1->tel_office, 13);
                if (new_content != NULL)
                {
                    strcpy(emp1->tel_office, new_content);
                    free(new_content);
                }
                break;
            case '6':
                new_content = modi_field("家庭电话", emp1->tel_home, 13);
                if (new_content != NULL)
                {
                    strcpy(emp1->tel_home, new_content);
                    free(new_content);
                }
                break;
            case '7':
                new_content = modi_field("移动电话", emp1->mobile, 12);
                if (new_content != NULL)
                {
                    strcpy(emp1->mobile, new_content);
                    free(new_content);
                }
                break;
            case '8':
                new_content = modi_field("QQ号码", emp1->qq, 13);
                if (new_content != NULL)
                {
                    strcpy(emp1->qq, new_content);
                    free(new_content);
                }
                break;
            case '9':
                new_content = modi_field("住址", emp1->address, 30);
                if (new_content != NULL)
                {
                    strcpy(emp1->address, new_content);
                    free(new_content);
                }
                break;
            
            default:
                break;
            }
        } while (choice<'0' || choice>'9');
        gsave = 1;
        savedata();
        pritnf("\n已修改完毕，按任意键退出！\n");
        getchar();
    }
}

/*
读取数据
*/
void readdata(void)
{
    FILE *fp;
    EMP *emp1;
    
    if ((fp=fopen("employee.dat", "rb")) == NULL)
    {
        gfirst = 1;
        return;
    }
    while (!feof(fp))
    {
        emp1 = (EMP*)malloc(sizeof(EMP));
        if (emp1 == NULL)
        {
            printf("内存分配失败！\n");
            getchar();
            return;
        }
        fread(emp1, sizeof(EMP), 1, fp);
        if (feof(fp))
            break;
        if (emp_first == NULL)
        {
            emp_first = emp1;
            emp_end = emp1;
        }
        emp_end->next = NULL;
    }
    gfirst = 0;
    fclose(fp);
}

/*
重置密码
*/
void resetpwd()
{
    // 密码最多10位，最后一位用作储存 '\0'
    char pwd[11], pwd1[11],ch;
    FILE *fp1;
    int i;
    system("cls");

    printf("\n请输入旧密码：\n");
    // 13是 回车 的ASCII码，按下回车停止输入密码
    for (i=0; i<10 && ((pwd[i]=getchar()) != 13); i++)
        putch('*');
    pwd[i] = '\0';

    // 比较旧密码
    if (strcmp(password, pwd))
    {
        printf("\n密码错误，按任意键退出！\n");
        getchar();
        return;
    }
    do
    {
        pritnf("\n设置新密码，请不要超过8位：");
        for (i=0; i<8 && ((pwd[i]=getchar()) != 13); i++)
        {
            putch('*');
        }
        printf("\n请再确认一次密码：");
        for (i=0; i<8 && ((pwd1[i] = getchar()) != 13); i++)
            putch("*");
        pwd[i] = '\0';
        pwd1[i] = '\0';

        if (strcmp(pwd, pwd1) != 0)
            printf("\n两次密码输入不一致，请重新输入！\n");
        else
            break;
    } while (1);
    
    if ((fp1 = fopen("config.bat", "wb")) == NULL)
    {
        printf("\n创建系统失败，按任意键退出！");
        getchar();
        exit(1);
    }

    i = 0;
    while (pwd[i])
    {
        putw(pwd[i], fp1);
        i++;
    }
    // 关闭文件流
    fclose(fp1);
    printf("\n密码修改成功，按任意键退出！\n");
    getchar();
    return;
}
void savedata()
{
    FILE *fp;
    EMP *emp1;
    if (gsave == 0)
        return;
    if ((fp=fopen("employee.dat", "wb")) == NULL)
    {
        printf("打开文件employee,dat 出错！\n");
        getchar();
        return;
    }
    emp1 = emp_first;
    while (emp1)
    {
        fwrite(emp1, sizeof(EMP), 1, fp);
        emp1 = emp1->next;
    }
    gsave = 0;
    fclose(fp);
}